Observable与Alamofire
Observable
Observable也就是一个被观察的对象,是一个事件序列,订阅者可以订阅它,监测事件的发生(Next\Complete\Error)。是不是听到这里就感觉这货有点像KVO?
热信号vs冷信号
信号分两种,热信号在它创建的时候就开始推送事件,这意味着如果后面有订阅者来的时候,就可能会错过一些事件。而冷信号则不会,只有在它被订阅的时候,它才会发送事件,这可以保证后面即使有订阅者中途加入的时候也能收到完整的事件序列。
获得Observable
要得到一个Observable有两种方式,一种是RxSwift已经提供了的(这里你可能需要引入RxCocoa),一种是自己创建。比如你有一个UITextfield,你要订阅其text的变化,就可以通过textfield.rx_text来获得这个Observable
func fetchClubList(fromPage page:Int) -> Observable<[ClubTableCellViewModel]>{
return create{ (observer ) -> Disposable in
Alamofire.request(Method.GET, "http://www.mocky.io/v2/560a046995e00cc208981280").responseArray{[unowned self]
(results:[ClubModel]?, err:ErrorType?) -> Void in
if let _ = err{
observer.on(Event.Error(err!))
}else{
if let cellVMs = (results?.map{ClubTableCellViewModel(club: $0)}){
if page == 0{
self.cellViewModels.removeAll()
}
self.cellViewModels.appendContentsOf(cellVMs)
observer.on(Event.Next(self.cellViewModels))
observer.on(Event.Completed)
}else{
//TODO: error handle
}
}
}
return NopDisposable.instance
}
}
这样就创建了一个Observable<[ClubModel]>,当他上面有事件发生的时候,我们可以做相应的操作。除了create,还可以通过never()创建一个什么都不发送的空序列,用empty()创建一个空序列但会发送.Complete等等。
信号的操作
常用的操作符有map,flatMap,subscribe,doOn,retry等等,具体的用法在它的文档中有具体说明。比如在我的demo里,需要根据页码加载列表数据。可以像这样做,在我的UIViewController里先创建一个属性:
var page : Variable<Int> = Variable(0)
接下来订阅这个page
self.page
.throttle(0.5, MainScheduler.sharedInstance)
.doOn{ [unowned self] value in
self.refreshCtrl.enabled = false
}
.flatMap {[unowned self] in
self.viewModel.fetchClubList(fromPage: $0)
.doOn{ [unowned self] in
self.refreshCtrl.endRefreshing()
self.refreshCtrl.enabled = true
}
.retry()
.catchErrorJustReturn([])
}
.bindTo(self.clubList.rx_itemsWithCellIdentifier("clubCell")){(_, viewModel, cell: ClubListCell) in
cell.viewModel = viewModel
}
.addDisposableTo(self.dispose)
这段代码里实现了在page发生变化的时候自动去请求服务端的数据,然后刷新tableview。throttle保证了事件序列发送的频率不会过快,doOn在每次.Next到来之前让我们有机会做些额外的处理,页码变化通过flatMap触发API调用,然后把得到的数据绑定到每个cell上面。
通过RxSwift整个代码量减少了很多,也变得更加易读,是不是感觉很棒!现在了解的也不够多,欢迎大家一起来交流
func getSprites() -> Observable<AnyObject?> {
return create{ observer in
var request = Alamofire.request(.GET, "https://epoquecore.com/sprites", parameters: nil)
.response({ (request, response, data, error) in
if((error) != nil){
sendError(observer, error!);
}else{
sendNext(observer, data);
sendCompleted(observer);
}
});
return AnonymousDisposable {
request.cancel()
}
}
}